package com.ruoyi.web.controller.tool.designpattern.behavioralPatterns.visitor;

import java.util.ArrayList;
import java.util.List;

// 访问者接口
interface Visitor {
    //访问元素实现方法
    void visit(Element element);
}

// 具体访问者A类
class ConcreteVisitorA implements Visitor {
    /**
     * 访问者A,对元素的处理方法
     * @param element
     */
    @Override
    public void visit(Element element) {
        System.out.println("具体访问者A访问了" + element.getClass().getSimpleName());
    }
}

// 具体访问者B类
class ConcreteVisitorB implements Visitor {
    //访问者B，对元素的处理方法
    @Override
    public void visit(Element element) {
        System.out.println("具体访问者B访问了" + element.getClass().getSimpleName());
    }
}

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// A实现元素类
class ConcreteElementA implements Element {
    //元素A的你
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// B实现元素类
class ConcreteElementB implements Element {
    //元素B的实现方法
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 维护了一个元素的集合，并提供了遍历这些元素的方法
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void attach(Element element) {
        elements.add(element);
    }

    public void remove(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

/*
访问者模式是一种行为设计模式，它允许您在不改变元素类的情况下定义新操作。
访问者模式将算法与对象结构分离，使得可以在不改变对象结构的前提下定义新的操作。
这种模式适用于当一个对象结构包含多个不同类型的对象，并且需要对这些对象进行不同的处理操作时。

在访问者模式中，主要包括以下角色：
1. Visitor（访问者）：定义了对每个元素对象访问时所要执行的操作。
2. ConcreteVisitor（具体访问者）：实现了Visitor接口，提供了对每个具体元素对象的具体访问操作。
3. Element（元素）：定义了一个accept方法，用于接受访问者的访问。
4. ConcreteElement（具体元素）：实现了Element接口，实现了accept方法，用于接受访问者的访问。
5. ObjectStructure（对象结构）：维护了一个元素的集合，并提供了遍历这些元素的方法。
 */
public class Test {
    public static void main(String[] args) {
        //元素集合(算法)，添加各类元素
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.attach(new ConcreteElementA());
        objectStructure.attach(new ConcreteElementB());
        //访问者A
        Visitor visitorA = new ConcreteVisitorA();
        //访问者B
        Visitor visitorB = new ConcreteVisitorB();

        objectStructure.accept(visitorA);
        objectStructure.accept(visitorB);
    }
}